#!/usr/bin/python
#coding=utf-8

# Steven Lian modified on 2016/12/25
# Purpose: for weChat airkiss service test

import json, platform
import redis
import sys
import logging

import hashlib
from redisHandle import *
import MySQLdb
import loRaTermianlCoder

#common cmd list
LORA_CMD_NULL_CMD = '0' #空命令,无需解释和执行
LORA_CMD_EXTEND_CMD  = '1'    #扩展命令,用于避免两个字节的命令类型不够的情况
LORA_CMD_ACK_SUCCESS = '2' #上次命令的应答，成功
LORA_CMD_ACK_FAIL = '3' #上次命令的应答，失败

LORA_CMD_REGISTRATION_REQUEST  = '10'   #服务登记请求，一个Terminal向router申请加入LoRa网络,同时会上传自己的唯一号 devID(IMEI),MAID(制造商代号)和PID(项目代号)
LORA_CMD_REGISTRATION_FEEDBACK  = '11'   #服务登记回馈，一个Terminal向router申请加入LoRa网络,同时会下发内部地址
LORA_CMD_REGISTRATION_REPORT  = '12'   #服务登记状态报告，一个router向上级报告加入网络分配情况
LORA_CMD_ADDR_REQUEST = '13'   #内部地址分配请求,一般是一个Terminal加入一个LoRa后,需要新分配或者获取已经分配的内部地址。
LORA_CMD_ADDR_FEEDBACK = '14'   #内部地址分配回馈,返回新分配或者获取已经分配的内部地址。
LORA_CMD_SYNC_CMD  = '15'  #router 同步,Terminal发送的开始时间,以及,分组和顺序
LORA_CMD_SYNC_TIME = '16'   # router 同步时间
LORA_CMD_SYNC_RANDOM  = '17'  #router 给出自由time slot,等需要发送设备请求，注册等信息的设备。
LORA_CMD_VERIFY_REQUEST = '18' #要求验证对方设备的真伪，需要发送一组随机数,至少是8个字节的数据,
LORA_CMD_VERIFY_FEEDBACK = '19' #验证反馈,回送对方8个字节的数据,和对应的MD5或者其他方式的hash结果,结果不少于8个字节。
LORA_CMD_DHCP_POOL_REQUEST  = '20' #host 主设备向上级服务器申请一个内部地址池
LORA_CMD_DHCP_POOL_FEEDBACK = '21' #上级服务器对 host 主设备向申请一个内部地址池请求的回应,给一个段落(开始和结束)
LORA_CMD_ADDR_CHANGE = '22' #对特定设备内部地址变更的通知,是对LORA_CMD_ADDR_REQUEST/LORA_CMD_ADDR_FEEDBACK的增强,格式和LORA_CMD_ADDR_FEEDBACK相同
LORA_CMD_FREQ_CHANGE = '23' #对特定设备通信频率变更的通知,
LORA_CMD_ADDR_REJECT = '24' #对特定设备拒绝服务的通知,
LORA_CMD_DATA_REPORT = '25' #数据上报消息，或者是状态上报消息


#application cmd list
LORA_CMD_APP_EXTEND_CMD  = '256' #应用扩展命令集合
LORA_CMD_APP_FMRADIO = '257' #FM Radion APPLICATION CMD

##redis 客户端初始化
dbW = getRedisDB(host="127.0.0.1", port=6379, db=9)
dbR = getRedisDB(host="10.102.9.143", port=6379, db=9)
redisDB = RedisHandle(dbW=dbW, dbR=dbR)

try:
    conn = MySQLdb.connect(host='127.0.0.1', user='root', passwd='password', db='lora', port=3306,charset='utf8')
    # cur = conn.cursor()
    # cur.execute('select * from dev_status')
    # cur.close()
    # conn.close()
except MySQLdb.Error, e:
    print "Mysql Error %d: %s" % (e.args[0], e.args[1])





_DEBUG=False
# 是否将日志写到db中
_TOLOG = True  

if _DEBUG ==True:
    import pdb
    pdb.set_trace()

# Redis/mongodb server information  BEGIN  
_REDIS_PORT=6379
_REDIS_DB=2


if platform.system() == 'Linux' :
    _REDIS_SERVERADDR = "127.0.0.1" 
    _WINDOWS_FLAG=False
else:
    _WINDOWS_FLAG=True
    sys.path.append("..\\..")
    #_REDIS_SERVERADDR = "118.192.76.159"
    _REDIS_SERVERADDR = "120.132.55.236"
    #client = pymongo.MongoClient("118.192.76.159", 28088)

#redis server
if _WINDOWS_FLAG<>True:
    controlServer = redis.ConnectionPool(host=_REDIS_SERVERADDR, port=_REDIS_PORT, db=_REDIS_DB)
    rControl = redis.Redis(connection_pool=controlServer)

#log BEGIN
# 0-->ALL, 1 -->ERROR 
_LOG_LEVEL=0 
if _WINDOWS_FLAG == False :
    uwsgilogfile="../../log/uwsgilog"
else :
    uwsgilogfile="uwsgilog"


# the function to set log file, SL:2014/10/3
def setlog(title,logfile) : 
    logger = logging.getLogger(title)   
    formatter = logging.Formatter('%(name)-12s %(asctime)s %(levelname)-8s %(message)s')    
    file_handler = logging.FileHandler(logfile) 
    #file_handler = TimedRotatingFileHandler(logfile,when="D")
    file_handler.setFormatter(formatter)        
    #stream_handler = logging.StreamHandler(sys.stderr) 
    logger.addHandler(file_handler) 
    #logger.addHandler(stream_handler)  
    logger.setLevel(logging.INFO)   
    return logger

uwsgilog = setlog("TEST",uwsgilogfile)
#log END


#count for typeID
gTokenPrefix="TESTID."


def getTokenVal(token, val=0):
    global gTokenPrefix, rControl
    result=0
    if _WINDOWS_FLAG<>True:
        realToken=gTokenPrefix+token
        nExist=rControl.exists(realToken)
        if nExist>0:
            if val==0:
                nCount=rControl.get(realToken)
            else:
                nCount=rControl.incr(realToken, val)
            nCount=int(nCount)
        else:
            nCount=-1
        result =nCount
    return result


# setTokenVal: 
# request: token and value, 
# return: current token count
def setTokenVal(token, val):
    global gTokenPrefix, rControl
    result=0
    if _WINDOWS_FLAG<>True:
        realToken=gTokenPrefix+token
        rControl.set(realToken, val)
        nCount=rControl.get(realToken)
        nCount=int(nCount)
        result =nCount
    return result

def embededLog(param):
    return param


# del a Token: 
# request: token 
# return: 
def delAToken(token):
    global gTokenPrefix, rControl
    result=0
    if _WINDOWS_FLAG<>True:
        realToken=gTokenPrefix+token
        nCount=rControl.delete(realToken)
        nCount=int(nCount)
    return result
    
def jsonDumps(data):
	return json.dumps(data,separators=(',', ':'))	 


def checkSignature(signature, token, timestamp, nonce):
    result=False
    aList=[]
    aList.append(token)
    aList.append(timestamp)
    aList.append(nonce)
    aList.sort()
    strT="".join(aList)
    m=hashlib.sha1()
    m.update(strT)
#    print m.hexdigest()
#    print signature
    if (signature ==m.hexdigest() ):
        result=True
    return result
        
    
    
    

def get(getdata):
    result=""
    token="lvairkisstest"
    try:
        if (getdata[0:7]=="echostr"):
            set1=getdata.split("&")
            aSet={}
            for a in set1:
                set2=a.split("=")
                aSet[set2[0]]=set2[1]
            #result=getdata[8:]
            if (checkSignature(aSet["signature"], token, aSet["timestamp"], aSet["nonce"]))==True:
                result=aSet["echostr"]
    except:
        pass
    return result

def post(postdata,env):
    result={"pushID":"192.168.0.1", "len":0,"data":[]}
    data = ""

    try:
        d = loRaTermianlCoder.to_decode_data(postdata)
        uwsgilog.info('R(decode):' + jsonDumps(d))
        #d = json.loads(postdata)
        ##{“pushID”:”192.168.0.1”, “len”:0,“data”:[]} 无数据上报
        if int(d["len"]) == 0:
            result = handleNoData(d)
        else:
            ###请求注册
            if d["data"][0]["CMD"] == LORA_CMD_REGISTRATION_REPORT and d["data"][0]["from"] == "0.0.0.0":
                result = handleRegistration(d)
            ##注册失败
            elif d["data"][0]["CMD"] == LORA_CMD_REGISTRATION_REPORT and d["data"][0]["from"] == "":
                result = handleRegFailure(d)
            ##注册成功
            elif d["data"][0]["CMD"] == LORA_CMD_REGISTRATION_REPORT:
                result = handleRegSuccess(d)
            ##上报状态
            elif d["data"][0]["CMD"] == LORA_CMD_APP_FMRADIO and d["data"][0]["appCMD"] == '21' :
                result = handleStatus(d)
            ##修改频率
            elif d["data"][0]["CMD"] == LORA_CMD_APP_FMRADIO and d["data"][0]["appCMD"] == '0':
                result = handleFrequence(d)
            ##修改音量
            elif d["data"][0]["CMD"] == LORA_CMD_APP_FMRADIO and d["data"][0]["appCMD"] == '4':
                result = handleSound(d)

    except:
        pass
    return result


def request(postdata, env):
    if _LOG_LEVEL ==0:
        #uwsgilog.info('R(env):'+ str(env))
        uwsgilog.info('R(data):'+ str(postdata))
    REQUEST_METHOD=env["REQUEST_METHOD"]
    QUERY_STRING=env["QUERY_STRING"]
    IP = env["REMOTE_ADDR"]
    if REQUEST_METHOD=="GET":
        data=get(QUERY_STRING)
    else:
        data=post(postdata, IP)
        data=jsonDumps(data)
    
    if _LOG_LEVEL ==0:
        uwsgilog.info( 'S:'+data )
    else:
        uwsgilog.error('S:'+data)
        
    return data


if platform.system() <> 'Linux' or _DEBUG==True:
    IP='127.0.0.1'


    msg='{"token":"100000","CMD":"get"}'
    msg='{"token":"100000","CMD":"set","value":100}'
    #msg='{"token":"100000","CMD":"del"}'
    #msg='{"token":"100000","CMD":"el"}'
    #msg='{"KK":"100000","CMD":"del"}'
    msg='{"token":"100000","CMD":"log","param":"test sss"}'
    envmsg='{"wsgi.multiprocess": "True", "REQUEST_METHOD": "GET", "PATH_INFO": "/airkiss", \
    "SERVER_PROTOCOL": "HTTP/1.0", \
    "QUERY_STRING": "echostr=BWPXAGYUNGNOCCXMWUUD&nonce=2043548072&signature=628c5145f892a55c10c525e4572ccfc655cdab65&timestamp=1482664876", \
    "CONTENT_LENGTH": "", "HTTP_CONNECTION": "keep-alive", "SERVER_NAME": "localhost",\
    "REMOTE_ADDR": "101.226.102.24", "wsgi.url_scheme": "http", "SERVER_PORT": "80", \
    "uwsgi.node": "10-9-23-219.localdomain", "DOCUMENT_ROOT": "/usr/local/nginx/html", \
    "uwsgi.core": 0, "wsgi.input": "<uwsgi._Input object at 0x7f41490641b0>", \
    "HTTP_HOST": "ss1.chakonger.net.cn", "wsgi.multithread": "True", \
    "HTTP_CACHE_CONTROL": "max-age=259200", \
    "REQUEST_URI": "/airkiss?echostr=BWPXAGYUNGNOCCXMWUUD&nonce=2043548072&signature=628c5145f892a55c10c525e4572ccfc655cdab65&timestamp=1482664876", \
    "HTTP_ACCEPT": "*/*", "wsgi.version":"(1, 0)", "wsgi.run_once": "False", \
    "wsgi.errors": "<open file wsgi_errors, mode w at 0x22e7d20>",\
    "REMOTE_PORT": "59728", "uwsgi.version": "2.0.13.1", "CONTENT_TYPE": "", \
    "wsgi.file_wrapper": "<built-in function uwsgi_sendfile>"}'
    
    env=json.loads(envmsg)
    t=request(msg,env)

    print t
def handleNoData(dic):
    result={"pushID":dic["pushID"], "len":'0',"devTodo":[]}
    arr = redisDB.dbR.lrange(dic["pushID"],0,9)
    result["devTodo"].extend(arr)
    result["len"] = str(len(arr))
    return result

#处理注册信息
def handleRegistration(d):
    sql = r'select segment_name from lora.net_segment left join lora.dev_status on lora.net_segment.segment_name = lora.dev_status.address where address is null limit 0,1'
    cur = conn.cursor()
    cur.execute(sql)
    results = cur.fetchall()
    result = {"pushID":results[0][0],"len":'1',"devTodo":[{"CMD":LORA_CMD_REGISTRATION_FEEDBACK, "from":"10.0.0.1", "to": results[0][0], \
     "seq":"12","devID":"12345670","addr":"192.168.0.1","val":"BBCCDDEEFF"}]}
    return result

def handleRegFailure(d):
    result = {"pushID":d["pushID"], "len":'0',"devTodo":[]}
    return result

def handleRegSuccess(d):
    result = {"pushID": d["pushID"], "len": '0', "devTodo": []}
    return result


#处理设备上报状态
def handleStatus(d):
    result = {"pushID": "192.168.0.1", "len": '0', "devTodo": []}
    return result
#处理修改频率
def handleFrequence(d):
    redisDB.dbW.rpush(d["pushID"],jsonDumps(d))
    result = {"pushID": "192.168.0.1", "len": '0', "devTodo": []}
    return result
##修改音量
def handleSound(d):
    redisDB.dbW.rpush(d["pushID"], jsonDumps(d))
    result = {"pushID": "192.168.0.1", "len": '0', "devTodo": []}
    return result

##查询sql 返回true就是存在，否则返回false
def queryTableHasValue(con,sql):
    try:
        cur = con.cursor()
        num = cur.execute(sql)
        cur.close()
        if num!=0:
            return True
        return False
    except MySQLdb.Error, e:
        print "Mysql Error %d: %s" % (e.args[0], e.args[1])
        return False


